<?php

declare(strict_types=1);

namespace Core;

/**
 * 基础控制器类
 *
 * 所有应用控制器应继承此类，以获得对核心 App 实例的便捷访问。
 * 通过 $this->app，子类可以调用 App 类中定义的各种功能，
 * 如数据库查询、输入处理、JSON 响应、CSRF 验证等。
 */
abstract class Controller
{
    /** @var App 应用核心实例 */
    protected App $app;

    /**
     * Controller constructor.
     *
     * 在构造函数中获取 App 的单例实例。
     * 
     * @param App|null $app (可选) App 实例。如果为 null，将自动从单例获取。
     *                      这个参数主要是为了未来可能的依赖注入或测试便利性而设计。
     */
    public function __construct(?App $app = null)
    {
        // 优先使用传入的实例（便于测试或特殊场景）
        $this->app = $app ?? App::getInstance();
    }

    /**
     * 渲染视图文件
     * 
     * @param string $view 视图文件名（不含扩展名）
     * @param array $data 传递给视图的数据
     */
    protected function render(string $view, array $data = []): void
    {
        // 获取视图路径
        $viewPath = $this->app->getConfig()['view_path'] ?? __DIR__ . '/../app/views';
        $fullPath = rtrim($viewPath, '/') . '/' . $view . '.php';

        if (!file_exists($fullPath)) {
            throw new \Exception("视图文件不存在: " . $fullPath);
        }

        // 提取数据到局部变量
        extract($data);

        // 开始输出缓冲
        ob_start();
        require $fullPath;
        $content = ob_get_clean();

        // 发送响应
        echo $content;
    }

    /**
     * 获取当前登录用户
     */
    protected function getCurrentUser(): ?array
    {
        if (!empty($_SESSION['user']) && !empty($_SESSION['user']['logged_in'])) {
            return $_SESSION['user'];
        }
        return null;
    }

    // 获取Flash服务实例
    protected function flash(): \Core\Flash
    {
        return $this->app->get('flash');
    }

    // 便捷方法：设置闪存数据
    protected function withErrors(array $errors): void
    {
        $this->flash()->set('errors', $errors);
    }

    // 便捷方法：设置旧输入
    protected function withInput(array $data): void
    {
        $this->flash()->set('old', $data);
    }

    // 便捷方法：设置成功/错误消息
    protected function success(string $message): void
    {
        $this->flash()->set('success', $message);
    }

    protected function error(string $message): void
    {
        $this->flash()->set('error', $message);
    }
}
